package halftone.errdiff.pipeline

import chisel3._
import chisel3.util.{Counter, Decoupled}
import halftone.ErrDiffConfig
import halftone.errdiff.ErrDiffCorePipParam._
import tools.bus.BramNativePortFull

class WriteBinaryPip(config: ErrDiffConfig) extends Module {
  val io = IO(new Bundle {
    val in  = Flipped(Decoupled(new ErrorOut2WriteBinaryPip(config.posWidth)))
    val img = Flipped(new BramNativePortFull(config.bramDataBits, config.bramAddrBits))
    val out = Decoupled()
    val end = Output(Bool())
  })

  // Registers
  val pos         = Reg(UInt(config.posWidth.W))
  val end = RegInit(false.B)
  val busy        = RegInit(false.B)
  val resultValid = RegInit(false.B)

  io.out.valid := resultValid
  io.in.ready  := true.B
  // useless signals
  io.out.bits := DontCare

  /*
   * Write binary pixel to image storage
   */
  io.img.en   := io.in.fire
  io.img.we   := io.in.fire
  io.img.addr := io.in.bits.pos + config.ddrBaseAddr.U
  io.img.din  := Mux(io.in.bits.bval, 255.U(config.pixelWidth.W), 0.U(config.pixelWidth.W))

  val (cnt, cntWrap) = Counter(busy && !resultValid, CycleNr)

  when(pos.andR) {
    end := true.B
  }
  io.end := end

  when(cntWrap) { resultValid := true.B }
  when(io.out.fire) {
    resultValid := false.B
  }
  when(io.in.fire) {
    busy := true.B
    pos := io.in.bits.pos
  }
}
